
#ifndef __APPLE__

#include <stdio.h>
#include <pthread.h>
#include <iostream>
#include <cstring>
#include <queue>
#include <csignal>
#include "public.h"
#include "../include/HCNetSDK.h"
#include "HttpConnect.h"

typedef struct tagALARM_MSG {
    BYTE byCardNo[ACS_CARD_NO_LEN];
    char dateTime[32];

} ALARM_MSG;


std::queue<ALARM_MSG> myQueue;
pthread_t sendingThread;
bool stoped = false;
HttpConnect http;

using namespace std;

BOOL CALLBACK MSesGCallback(LONG lCommand, NET_DVR_ALARMER *pAlarmer, char *pAlarmInfo, DWORD dwBufLen, void *pUser) {
    if (COMM_ALARM_ACS == lCommand) {
        NET_DVR_ACS_ALARM_INFO struAcsAlarmInfo = {0};
        memcpy(&struAcsAlarmInfo, pAlarmInfo, sizeof(struAcsAlarmInfo));
//        printf("Command: dwMajor=0x%x, dwMinor=0x%x\n", struAcsAlarmInfo.dwMajor, struAcsAlarmInfo.dwMinor);
        if (0x5 == struAcsAlarmInfo.dwMajor) {
            size_t len = strlen((char *) struAcsAlarmInfo.struAcsEventInfo.byCardNo);
            if (len > 0) {
                ALARM_MSG alarmMsg = {0};
                sprintf(alarmMsg.dateTime, "%04d-%02d-%02d+%02d%s%02d%s%02d", struAcsAlarmInfo.struTime.dwYear,
                        struAcsAlarmInfo.struTime.dwMonth, struAcsAlarmInfo.struTime.dwDay,
                        struAcsAlarmInfo.struTime.dwHour, "%3A", struAcsAlarmInfo.struTime.dwMinute, "%3A",
                        struAcsAlarmInfo.struTime.dwSecond);
                memcpy(alarmMsg.byCardNo, struAcsAlarmInfo.struAcsEventInfo.byCardNo, ACS_CARD_NO_LEN);
                myQueue.push(alarmMsg);
                printf("number: %s, dateTime=%s\n", alarmMsg.byCardNo, alarmMsg.dateTime);
            }
        }
    }
    return true;
}


void *sendAlarmToServer(void *pv) {
    struct timespec ts;
    ts.tv_sec = 1;
    ts.tv_nsec = 0;
    while (!stoped) {
        nanosleep(&ts, NULL);

        if (myQueue.empty()) {
            continue;
        }

        ALARM_MSG msg = myQueue.front();
        myQueue.pop();
        try {
            http.postData("www.jsxrk.xin", "/public/api/nursery/education/checkon", (char *) msg.byCardNo,
                          msg.dateTime);
        } catch (exception e) {
            printf("exception: %s\n", e.what());
        }


    }
}

void signalHandler(int signum) {
    stoped = true;
    printf("Interrupt signal (%d) received.\n", signum);
}

//}

int main(int argc, char **argv) {
    char *deviceIp = argv[1];
    char *devicePort = argv[2];
    char *adminName = argv[3];
    char *adminPwd = argv[4];

    int port = atoi(devicePort);

    signal(SIGINT, signalHandler);
    signal(SIGTERM, signalHandler);

    NET_DVR_Init();
    NET_DVR_SetLogToFile(3, "./log");
    NET_DVR_SetConnectTime(2000, 1);
    NET_DVR_SetReconnect(10000, true);

    NET_DVR_USER_LOGIN_INFO struLoginInfo = {0};
    struLoginInfo.bUseAsynLogin = 0;
    strcpy(struLoginInfo.sDeviceAddress, deviceIp);
    struLoginInfo.wPort = (WORD) port;
    strcpy(struLoginInfo.sUserName, adminName);
    strcpy(struLoginInfo.sPassword, adminPwd);

    NET_DVR_DEVICEINFO_V40 struDeviceInfoV40 = {0};
    LONG lUserID = NET_DVR_Login_V40(&struLoginInfo, &struDeviceInfoV40);
    if (lUserID < 0) {
        printf("Login failed, error code: %d\n", NET_DVR_GetLastError());
        NET_DVR_Cleanup();
        return HPR_ERROR;
    }

    NET_DVR_SetDVRMessageCallBack_V31(MSesGCallback, NULL);
    NET_DVR_SETUPALARM_PARAM struSetupParam = {0};
    struSetupParam.dwSize = sizeof(NET_DVR_SETUPALARM_PARAM);
    LONG lHandle = NET_DVR_SetupAlarmChan_V41(lUserID, &struSetupParam);
    if (lHandle < 0) {
        printf("NET_DVR_SetupAlarmChan_V41 error, %d\n", NET_DVR_GetLastError());
        NET_DVR_Logout(lUserID);
        NET_DVR_Cleanup();
        return HPR_ERROR;
    }

    printf("NET_DVR_SetupAlarmChan_V41 OK");

    int ret = pthread_create(&sendingThread, NULL, sendAlarmToServer, NULL);
    if (ret != 0) {
        NET_DVR_CloseAlarmChan_V30(lHandle);
        printf("NET_DVR_CloseAlarmChan_V30 error\n");
        NET_DVR_Logout(lUserID);
        NET_DVR_Cleanup();
        return HPR_ERROR;
    }

    pthread_join(sendingThread, NULL);

    //撤销布防
    if (!NET_DVR_CloseAlarmChan_V30(lHandle)) {
        printf("NET_DVR_CloseAlarmChan_V30 error, %d\n", NET_DVR_GetLastError());
        NET_DVR_Logout(lUserID);
        NET_DVR_Cleanup();
        return HPR_ERROR;
    }

    NET_DVR_Logout(lUserID);
    NET_DVR_Cleanup();
    return HPR_OK;
}


#endif